﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;
using System.Web.Mvc;
using ProjectHopur23.Repositories;
using ProjectHopur23.Models;

namespace ProjectHopur23.Controllers
{
	public class HomeController : Controller
	{
		#region Variables
		private IRepository rep = null;
		#endregion

		#region Constructors
		public HomeController()
		{
			rep = new Repository();
		}

		public HomeController(IRepository r)
		{
			rep = r;
		}
		#endregion

		#region Functions
		public ActionResult About()
		{
			return View();
		}

		/// <summary>
		/// The index (front page) lists a lot of the basic data such as the logged in user's invitations to games
		/// games that are waiting for players, games that are ready to play or already playing, high scores, online users...
		/// </summary>
		public ActionResult Index()
		{
			GameController gc = new GameController();
			HomeViewModel h = new HomeViewModel();

			List<ActiveGameFrontViewModel> activeGamesPendingView = new List<ActiveGameFrontViewModel>();
			List<ActiveGameFrontViewModel> activeGamesFullView = new List<ActiveGameFrontViewModel>();
			IEnumerable<ActiveGame> allActiveGames = rep.GetAllActiveGames().OrderByDescending(x => x.ID);

			List<HighScoreViewModel> highScores = new List<HighScoreViewModel>();
			IEnumerable<UserProfile> highScoreUsers = gc.GetHighScores(10);

			List<string> oUsers = new List<string>();
			IEnumerable<UserProfile> onlineUsers = gc.GetOnlineUsers();

			List<InviteFrontViewModel> userInvitesView = new List<InviteFrontViewModel>();

			Game game;

			// Populare the two active games lists with entries from all active games
			// Games that are finished are of no interest to us here
			foreach(ActiveGame ag in allActiveGames)
			{
				if(ag.isFinished == false)
				{
					game = gc.GetGameByID(ag.gameId);
					if(game != null)
					{
						ActiveGameFrontViewModel agv = new ActiveGameFrontViewModel {
									gameName = game.name,
									gameEngName = game.engName,
									gameNickname = ag.name,
									gameActiveID = ag.ID,
									currentPlayers = gc.GetNumUsersInActiveGame(ag.ID) + gc.GetNumInvitesToGame(ag.ID),
									numberOfPlayers = ag.numberOfPlayers};

						if(ag.isFull == false)
						{
							activeGamesPendingView.Add(agv);
						}
						else
						{
							activeGamesFullView.Add(agv);
						}
					}
				}
			}

			foreach(UserProfile u in highScoreUsers)
			{
				highScores.Add(new HighScoreViewModel {
						name = u.UserName,
						score = u.score});
			}

			foreach(UserProfile u in onlineUsers)
			{
				oUsers.Add(u.UserName); 
			}

			if(HttpContext.User.Identity.IsAuthenticated == true)
			{
				IEnumerable<Invite> userInvites = GetInvitesForUser(gc.GetUserByName(HttpContext.User.Identity.Name).UserId);

				foreach(Invite i in userInvites)
				{
					game = gc.GetGameByID(gc.GetActiveGameByID(i.activeGameId).gameId);

					userInvitesView.Add(new InviteFrontViewModel {
								activeGameId = i.activeGameId,
								hostName = gc.GetUserByID(i.hostId).UserName,
								guestId = i.guestId,
								gameName = game.name,
								gameEngName = game.engName});
				}
			}

			// Our big view model class instance for the front page is now linked to all the data collected abve
			h.activeGamesPending = activeGamesPendingView;
			h.activeGamesFull = activeGamesFullView;
			h.popularGames = GetPopularGames(2);
			h.highScores = highScores;
			h.onlineUsers = oUsers;
			h.userInvites = userInvitesView;

			return View(h);
		}

		[Authorize]
		public ActionResult AcceptInvitation(int? agId, int? guestId)
		{
			if(agId == null || guestId == null)
			{
				return View("Error");
			}

			GameController gc = new GameController();
			gc.AcceptInvitation(agId.Value, guestId.Value);

			return RedirectToAction("Index");
		}

		[Authorize]
		public ActionResult RejectInvitation(int? agId, int? guestId)
		{
			if(agId == null || guestId == null)
			{
				return View("Error");
			}

			GameController gc = new GameController();
			gc.RejectInvitation(agId.Value, guestId.Value);

			return RedirectToAction("Index");
		}

		///<summary>
		///This method returns a view that has a full list of available games
		///</summary>
		public ActionResult Games()
		{
			IEnumerable<Game> allGames = rep.GetAllGames();

			return View(allGames);
		}
		#endregion

		#region DatabaseFunctions
		public IEnumerable<Game> GetPopularGames(int numGames)
		{
			IEnumerable<Game> popularGames = (from g in rep.GetAllGames()
								orderby g.timesPlayed descending
								select g).Take(numGames);

			return popularGames;
		}

		public IEnumerable<Invite> GetInvitesForUser(int id)
		{
			IEnumerable<Invite> theInvites = from i in rep.GetAllInvites()
							where i.guestId == id && i.isToggled == false
							select i;

			return theInvites;
		}
		#endregion
	}
}
